# Copyright 2009 http://www.yuntien.com
# Licensed under the Apache License, Version 2.0

from google.appengine.ext import db
from google.appengine.api import memcache
from ytblog.model.tag import TagInfo
import ytblog.config
import cache

class Blog(db.Model):
  author = db.UserProperty()
  title = db.StringProperty(multiline=False)
  date = db.DateTimeProperty(auto_now_add=True)
  update = db.DateTimeProperty(auto_now=True)
  tags = db.StringListProperty()
  content = db.TextProperty()
  points = db.IntegerProperty(default=0)
  popular = db.BooleanProperty(default=False)

  @classmethod
  def get_by_str_id(cls, id):
    try:      
      id = int(id)
      blog = Blog.get_by_id(id)
      return blog
    except:
      return None
  
  def get_parent(self):
    return None
  
  @cache.delete_all_cache
  def delete(self):
    self.remove_tags()
    db.Model.delete(self)
    
  @cache.delete_all_cache
  def put(self):
    self.add_tags_to_db()    
    db.Model.put(self)

  def add_tags(self, tag_str):
    self._tag_str = tag_str

  def add_tags_to_db(self):
    if not hasattr(self, '_tag_str'):
      return
  
    if self._tag_str == self.get_tag_str():
      return
      
    #tag max number should be less than 10, for better performance
    tags = self._tag_str.split('/')[0:ytblog.config.MAX_TAG_NUM]
    #remove invalid tag
    tags = [tag for tag in tags if tag != '']
    #to add
    tags_new = [tag for tag in tags if tag not in self.tags]
    #to delete
    tags_old = [tag for tag in self.tags if tag not in tags]
    
    try:
      for tag in tags_new:
        tag_info = TagInfo.get_or_insert_by_name(tag, name=tag)
        tag_info.number = tag_info.number + 1
        tag_info.put()
          
      self.remove_tags(tags_old)
    except:
      pass
    
    self.tags = tags
  
  def get_tag_str(self):
    return '/'.join(self.tags[0:ytblog.config.MAX_TAG_NUM])
    
  def remove_tags(self, tags=None):
    if tags is None:
      tags = self.tags
      
    try:
      for tag in tags:
        tag_info = TagInfo.get_by_name(tag)
        if tag_info and tag_info.number > 0: 
          tag_info.number = tag_info.number - 1
          tag_info.put()
    except:
      pass

class Comment(db.Model):
  blog = db.ReferenceProperty(Blog, required=True) 
  author = db.UserProperty()
  date = db.DateTimeProperty(auto_now_add=True)
  content = db.TextProperty()

  @classmethod
  def get_by_str_id(cls, id):
    try:      
      id = int(id)
      obj = Comment.get_by_id(id)
      return obj
    except:
      return None
  
  def get_parent(self):
    return None
  
  @cache.delete_cache(cache.RECENT_COMMENTS_KEY)
  def put(self):
    db.Model.put(self)

  @cache.delete_cache(cache.RECENT_COMMENTS_KEY)
  def delete(self):
    db.Model.delete(self)
    
  @classmethod
  def get_recent_comments(cls):
    key = cache.RECENT_COMMENTS_KEY
    data = memcache.get(key)
    if data is not None:
      return data
    else:
      data = Comment.all().order('-date').fetch(ytblog.config.RECENT_COMMENT_NUM)
      #filter invalid comments caused by deleted blogs
      data = [d for d in data if db.get(Comment.blog.get_value_for_datastore(d))]
      memcache.add(key, data)
      return data
  